package com.yonyou.hxjy.service.dingtalk.Impl.toysImpl;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.yonyou.hxjy.dao.JobLogDao;
import com.yonyou.hxjy.dao.ProcessinstanceMapper;
import com.yonyou.hxjy.entity.ProcessInstance;
import com.yonyou.hxjy.enums.OpenApiUrlEnum;
import com.yonyou.hxjy.model.JobLogModel;
import com.yonyou.hxjy.service.BaseApi;
import com.yonyou.hxjy.service.dingtalk.DingtalkAdvancePaymentToYs;
import com.yonyou.hxjy.service.dingtalk.DingtalkExpenseClaimToYs;
import com.yonyou.hxjy.service.dingtalk.DingtalkFundAllocationToYs;
import com.yonyou.hxjy.service.dingtalk.DingtalkProcessInstanceToYs;
import com.yonyou.hxjy.service.dingtalk.Impl.YsDataGetService;
import com.yonyou.hxjy.utils.RedisUtils;
import com.yonyou.hxjy.utils.YsQueryDtoSingletonUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class DingtalkProcessInstanceToYsImplTest extends BaseApi implements DingtalkProcessInstanceToYs{

    @Autowired
    private YsDataGetService ysDataGetService;

    @Resource
    public JobLogDao jobLogDao;

    @Autowired
    private DingtalkExpenseClaimToYs dingtalkExpenseClaimToYs;

    @Autowired
    private DingtalkNewExpenseClaimToYsImpl dingtalkNewExpenseClaimToYs;

    @Autowired
    private DingtalkAdvancePaymentToYs dingtalkAdvancePaymentToYs;

    @Autowired
    private DingtalkFundAllocationToYs dingtalkFundAllocationToYs;

    @Autowired
    private ProcessinstanceMapper processinstanceMapper;

    private static final Logger logger = LoggerFactory.getLogger(DingtalkProcessInstanceToYsImplTest.class);

    /**
     * 费用报销资金收款单保存到Ys中
     * @param jsonObjectList
     * @return
     */
    @Override
    public List<JSONObject> expenseClaim_toYsJson(List<JSONObject> jsonObjectList,List<String> processInstanceIdList) {
        return dingtalkExpenseClaimToYs.expenseClaim_toYsJson(jsonObjectList,processInstanceIdList);
    }

//    @Override
//    public List<JSONObject> expenseClaim_toYsJsonNew(List<JSONObject> jsonObjectList) {
////        return dingtalkExpenseClaimToYs.expenseClaim_toYsJsonNew(jsonObjectList);
//    }

    /**
     * 新费用报销资金收款单保存到Ys中
     * @param jsonObjectList
     * @return
     */
    @Override
    public List<JSONObject> newExpenseClaim_toYsJson(List<JSONObject> jsonObjectList) {
        return dingtalkNewExpenseClaimToYs.newExpenseClaim_toYsJson(jsonObjectList);
    }


    /**
     * 保存预付款收款单到Ys中
     * @param jsonObjectList
     * @return
     */
    @Override
    public List<JSONObject> advancePayment_toYsJson(List<JSONObject> jsonObjectList) {
        return dingtalkAdvancePaymentToYs.advancePayment_toYsJson(jsonObjectList);
    }

    @Override
    public List<JSONObject> newadvancePayment_toYsJson(List<JSONObject> jsonObjectList) {
        return dingtalkAdvancePaymentToYs.newadvancePayment_toYsJson(jsonObjectList);
    }

    /**
     * @param jsonObjectList
     * @return
     * 保存资金调拨订单付款单到Ys中
     */
    @Override
    public List<JSONObject> fundAllocation_toYsJson(List<JSONObject> jsonObjectList) {
        return dingtalkFundAllocationToYs.fundAllocation_toYsJson(jsonObjectList);
    }

    /**
     * 根据组织名称,开户组织名称匹配对应的默认银行账号
     */
    @Override
    public String getBankCode(String org_name,List<JSONObject> bankList){
        String bankCode = null;
        boolean defaultAccount = false;
        if (bankList!=null && !bankList.isEmpty()){
            for (JSONObject jsonObject : bankList) {
                String accountOrgIdName = jsonObject.getStr("accountOrgId_name");
                String orgidName = jsonObject.getStr("orgid_name");
                Integer acctType = jsonObject.getInt("acctType");
                //是否为默认账号
                if (jsonObject.containsKey("defineCharacter__YH")){
                   defaultAccount  = jsonObject.getBool("defineCharacter__YH");
                }
                if (accountOrgIdName!=null && accountOrgIdName.contains(org_name) && orgidName.contains(org_name) && defaultAccount){
                    bankCode = jsonObject.getStr("account");
                    return bankCode;
                }
            }
        }else {
            return null;
        }
        return bankCode;
    }


//    @Override
//    public String getVendorCode(String vendor_name,Map<String,Object> bankParamMap,List<JSONObject> vendorList){
//        String vendorCode = null;
//        JSONObject vendorDetails = null;
//        //参数汇总
//        Map<String,Object> dataMap = new HashMap<>();
//        //主表参数
//        Map<String,Object> paramMap = new HashMap<>();
//        //银行列表参数
//        List<Map<String,Object>> vendorBankList = new ArrayList<>();
//        //银行子表参数
//        Map<String,Object> vendorBankMap = new HashMap<>(paramMap);
//        //供应商存在判断条件
//        boolean flag = true;
//
//        if (vendorList==null && vendorList.isEmpty()){
//            return null;
//        }
//        try {
//            for (JSONObject jsonObject : vendorList) {
//
//                String vendorName = jsonObject.getStr("name");
//                String vendorclass_name = jsonObject.getStr("vendorclass_name"); //供应商类型
//                if (vendorName.contains(vendor_name)){   //供应商存在则获取详情判断是否存在银行账户
//                    flag = false;
//                    //获取供应商详情
//                    vendorDetails = ysDataGetService.getVendorBankCode(jsonObject.getStr("id"));
//                    //判断是否存在银行账户
//                    if (vendorDetails!=null && !vendorDetails.isEmpty()){
//                        List<String> vendorCodeList = new ArrayList<>();
//                        JSONArray vendorbanks = vendorDetails.getJSONArray("vendorbanks");
//                        //遍历获取供应商所有银行信息
//                        for (int i = 0;i<vendorbanks.size();i++){
//                            JSONObject vendorbank = vendorbanks.getJSONObject(i);
//                            vendorCodeList.add(vendorbank.getStr("account"));
//                        }
//                        if (vendorCodeList != null && vendorCodeList.contains(bankParamMap.get("account"))){
//                            //存在银行账户直接返回供应商编码
//                            vendorCode = vendorDetails.getStr("code");
//                            return vendorCode;
//                        }else {
//                            paramMap.put("code",vendorDetails.getStr("code"));
//                            paramMap.put("id",vendorDetails.getStr("id"));
//                            paramMap.put("_status","Update");
//                            vendorBankMap.put("currency_code","CNY");//币种id
//                            vendorBankMap.put("account",bankParamMap.get("account")); //银行账号
//                            vendorBankMap.put("openaccountbank",bankParamMap.get("openaccountbank")); //银行网点id
//                            vendorBankMap.put("bank",bankParamMap.get("bank")); //银行类别id
//                            vendorBankMap.put("accountname",bankParamMap.get("accountname")); //账户名称
//                            vendorBankMap.put("_status","Insert");
//                            vendorBankList.add(vendorBankMap);
//                            paramMap.put("vendorbanks",vendorBankList);
//                            dataMap.put("data", paramMap);
//                            System.out.println("供应商银行信息新增参数:"+dataMap);
//                            JSONObject jsonObject1 = ysDataGetService.addVendorBanks(dataMap);
//                            logger.info("供应商银行账号新增{}",jsonObject1.getStr("message"));
//                            return vendorCode = vendorDetails.getStr("code");
//                        }
//                    }else {
//                        logger.error("供应商详情信息数据错误!!");
//                    }
//                }
////                else if (vendorName.contains(vendor_name) && "内部单位".equals(vendorclass_name)){
////                    flag = false;
////                    vendorCode = "";
////                    return vendorCode;
////                }
//            }
//            //logger.info("供应商是否存在{}",flag);
//            //如果flag为false,则供应商已存在
//            if (flag){
//                //供应商档案不存在---新增
//                paramMap.put("code",generateRandomVendorCode());
//                paramMap.put("_status","Insert");
//                paramMap.put("org","666666");
//                paramMap.put("org_code","666666");
//                Map<String,Object> nameMap = new HashMap<>();
//                nameMap.put("zh_CN",vendor_name);
//                paramMap.put("name",nameMap);
//                paramMap.put("vendorclass_code","01");
//                vendorBankMap.put("currency_code","CNY");
//                vendorBankMap.put("account",bankParamMap.get("account")); //银行账号
//                vendorBankMap.put("openaccountbank",bankParamMap.get("openaccountbank")); //银行网点id
//                vendorBankMap.put("bank",bankParamMap.get("bank")); //银行类别id
//                vendorBankMap.put("accountname",bankParamMap.get("accountname")); //账户名称
//                vendorBankMap.put("_status","Insert");
//                vendorBankList.add(vendorBankMap);
//                paramMap.put("vendorbanks",vendorBankList);
//                dataMap.put("data", paramMap);
//                logger.info("供应商新增参数{}",dataMap);
//                JSONObject jsonObject1 = ysDataGetService.addVendorBanks(dataMap);
//                logger.info("供应商档案新增{}",jsonObject1.getStr("message"));
//                if (!jsonObject1.containsKey("data")){
//                    throw new RuntimeException("供应商档案新增"+jsonObject1.getStr("message"));
//                }
//                vendorCode = jsonObject1.getJSONObject("data").getStr("code");
//                return vendorCode;
//            }
//        }catch (Exception e){
//            logger.info(e.getMessage());
//        }
//        return vendorCode;
//    }

    /**
     * 获取供应商编码
     * @param vendorName
     * @param bankParamMap
     * @param vendorList
     * @return
     */
    @Override
    public String getVendorCode(String vendorName, Map<String, Object> bankParamMap, List<JSONObject> vendorList) {
        if (vendorList == null || vendorList.isEmpty()) {
            return null;
        }

        try {
            // 查找已有供应商
            Optional<JSONObject> matchedVendorOpt = findMatchingVendor(vendorName, vendorList);
            if (matchedVendorOpt.isPresent()) {
                JSONObject vendor = matchedVendorOpt.get();
                logger.info("找到匹配供应商: {}", vendor.getStr("name"));

                String vendorId = vendor.getStr("id");
                JSONObject vendorDetails = ysDataGetService.getVendorBankCode(vendorId);
                if (vendorDetails == null || vendorDetails.isEmpty()) {
                    logger.warn("供应商详情为空，ID: {}", vendorId);
                    return null;
                }

                // 判断是否存在银行账户
                boolean accountExists = hasBankAccount(vendorDetails, bankParamMap.get("account").toString());
                if (accountExists) {
                    return vendorDetails.getStr("code");
                } else {
                    // 新增银行账户并返回编码
                    return updateVendorWithNewBank(vendorDetails, bankParamMap);
                }
            } else {
                // 供应商不存在，新增
                return createVendorWithBank(vendorName, bankParamMap);
            }
        } catch (Exception e) {
            logger.error("获取或创建供应商编码时发生错误", e);
            throw new RuntimeException("获取或创建供应商编码失败", e);
        }
    }

    // ==================== 私有方法区 ====================

    /**
     * 查找匹配的供应商
     */
    private Optional<JSONObject> findMatchingVendor(String vendorName, List<JSONObject> vendorList) {
        return vendorList.stream()
                .filter(obj -> obj.getStr("name").contains(vendorName))
                .findFirst();
    }

    /**
     * 检查供应商是否有指定银行账户
     */
    private boolean hasBankAccount(JSONObject vendorDetails, String targetAccount) {
        JSONArray vendorbanks = vendorDetails.getJSONArray("vendorbanks");
        if (vendorbanks == null || vendorbanks.isEmpty()) {
            return false;
        }

        Set<String> accounts = new HashSet<>();
        for (int i = 0; i < vendorbanks.size(); i++) {
            JSONObject bank = vendorbanks.getJSONObject(i);
            String account = bank.getStr("account");
            if (account != null) {
                accounts.add(account);
            }
        }
        return accounts.contains(targetAccount);
    }

    /**
     * 更新供应商信息并添加新的银行账户
     */
    private String updateVendorWithNewBank(JSONObject vendorDetails, Map<String, Object> bankParamMap) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("code", vendorDetails.getStr("code"));
        paramMap.put("id", vendorDetails.getStr("id"));
        paramMap.put("_status", "Update");

        List<Map<String, Object>> vendorBankList = new ArrayList<>();
        Map<String, Object> bankMap = new HashMap<>();
        bankMap.put("currency_code", "CNY");
        bankMap.put("account", bankParamMap.get("account"));
        bankMap.put("openaccountbank", bankParamMap.get("openaccountbank"));
        bankMap.put("bank", bankParamMap.get("bank"));
        bankMap.put("accountname", bankParamMap.get("accountname"));
        bankMap.put("_status", "Insert");
        vendorBankList.add(bankMap);

        paramMap.put("vendorbanks", vendorBankList);

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("data", paramMap);

        logger.info("供应商银行信息新增参数: {}", dataMap);
        JSONObject result = ysDataGetService.addVendorBanks(dataMap);

        logger.info("供应商银行账号新增结果: {}", result.getStr("message"));
        return vendorDetails.getStr("code");
    }

    /**
     * 创建新供应商及其银行账户
     */
    private String createVendorWithBank(String vendorName, Map<String, Object> bankParamMap) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("code", generateRandomVendorCode());
        paramMap.put("_status", "Insert");
        paramMap.put("org", "666666");
        paramMap.put("org_code", "666666");

        Map<String, String> nameMap = new HashMap<>();
        nameMap.put("zh_CN", vendorName);
        paramMap.put("name", nameMap);
        paramMap.put("vendorclass_code", "01");

        List<Map<String, Object>> vendorBankList = new ArrayList<>();
        Map<String, Object> bankMap = new HashMap<>();
        bankMap.put("currency_code", "CNY");
        bankMap.put("account", bankParamMap.get("account"));
        bankMap.put("openaccountbank", bankParamMap.get("openaccountbank"));
        bankMap.put("bank", bankParamMap.get("bank"));
        bankMap.put("accountname", bankParamMap.get("accountname"));
        bankMap.put("_status", "Insert");
        vendorBankList.add(bankMap);

        paramMap.put("vendorbanks", vendorBankList);

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("data", paramMap);

        logger.info("供应商新增参数: {}", dataMap);
        JSONObject result = ysDataGetService.addVendorBanks(dataMap);

        logger.info("供应商档案新增结果: {}", result.getStr("message"));
        if (!result.containsKey("data")) {
            throw new RuntimeException("供应商档案新增失败: " + result.getStr("message"));
        }

        return result.getJSONObject("data").getStr("code");
    }

    /**
     * 资金付款单ys单个保存
     * @param paramMap
     * @return
     * @throws Exception
     */
    @Override
    public JSONObject sendPostToSaveFundPayment(Map<String,Object> paramMap) throws Exception {
        return JSONUtil.parseObj(doPost(YsQueryDtoSingletonUtil.getYsQueryDto().getGatewayUrl() + OpenApiUrlEnum.FUNDPAYMENT_SAVE, paramMap, YsQueryDtoSingletonUtil.getYsQueryDto()));
    }


    /**
     * 资金收款单ys单个保存
     * @param paramMap
     * @return
     * @throws Exception
     */
    @Override
    public JSONObject sendPostToSaveFundCollection(Map<String,Object> paramMap) throws Exception {
        return JSONUtil.parseObj(doPost(YsQueryDtoSingletonUtil.getYsQueryDto().getGatewayUrl() + OpenApiUrlEnum.FUNDCOLLECTION_SAVE, paramMap, YsQueryDtoSingletonUtil.getYsQueryDto()));

    }

    @Override
    public JSONObject sendPostToSubmit(Map<String, Object> paramMap) throws Exception {
        return JSONUtil.parseObj(doPost(YsQueryDtoSingletonUtil.getYsQueryDto().getGatewayUrl() + OpenApiUrlEnum.FUNDCOLLECTION_SUBMIT, paramMap, YsQueryDtoSingletonUtil.getYsQueryDto()));

    }


    /**
     * 时间类型转换
     * @param isoDateTime
     * @return
     */
    @Override
    public String dateFormChange(String isoDateTime ){
        // 使用DateTimeFormatter.ISO_ZONED_DATE_TIME解析ISO 8601格式的时间字符串
        ZonedDateTime targetZoneTime = ZonedDateTime.parse(isoDateTime, DateTimeFormatter.ISO_ZONED_DATE_TIME);

        // 打印转换后的时间
        //System.out.println("转换后的中国标准时间: " + targetZoneTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        return targetZoneTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 供应商编码随机生成
     * @return
     */
    public static String generateRandomVendorCode() {
        // 固定第一位为0
        StringBuilder number = new StringBuilder("0");

        // 创建一个包含 1~9 的列表
        List<Integer> digits = new ArrayList<>();
        for (int i = 1; i <= 9; i++) {
            digits.add(i);
        }

        // 随机打乱顺序后取前3个
        Collections.shuffle(digits);
        List<Integer> selected = digits.subList(0, 3);

        // 排序，按升序排列
        Collections.sort(selected);

        // 拼接成字符串
        for (Integer digit : selected) {
            number.append(digit);
        }
        return number.toString();
    }


    /**
     * xxl-job日志信息显示
     * @param code
     * @param oneL
     * @param mags
     */
    @Override
    public void InsertLogger(String code, String oneL, String mags,String jobClass) {  // 单据编号、是否成功、详细信息
        try {
            JobLogModel jobLogDTO = new JobLogModel();
            jobLogDTO.setJobClass(jobClass); // 执行器序号 -
            jobLogDTO.setJobCode(code);//单据编码
            jobLogDTO.setJobTime(new Date());
            jobLogDTO.setJobResult(oneL);//成功是0or1
            jobLogDTO.setJobResultMessage(mags);//成功是成功，失败是失败原因
            jobLogDTO.setJobLogUser("admin");//改成新华教育用户名称
            jobLogDao.insertJobLog(jobLogDTO);
        } catch (Exception e) {
            logger.error("插入日志错误：" + e.getMessage());
        }
    }

    /**
     * 通过审核人过滤数据
     * @param jsonObjectList
     * @return
     */
//    public List<JSONObject> filter_Reviewer(List<JSONObject> jsonObjectList){
//        List<JSONObject> filterList = new ArrayList<>();
//        for (JSONObject jsonObject:jsonObjectList){
//            JSONArray jsonArray = jsonObject.getJSONObject("result").getJSONArray("tasks");
//            for (int i = 0; i < jsonArray.size(); i++) {
//                JSONObject entries = jsonArray.getJSONObject(i);
//                if (entries.containsKey("userId") && entries.containsKey("status")){
//                    String userId = entries.getStr("userId");
//                    String status = entries.getStr("status");
//                    if ("RUNNING".equals(status) && "17127137219696885".equals(userId) || "1718785327792823".equals(userId)){
//                        filterList.add(jsonObject);
//                        break;
//                    }
//                }
//            }
//        }
//        System.out.println("过滤后的单据大小:"+filterList.size());
//        return filterList;
//    }

    /**
     * 处理响应结果
     * @param jsonObjectResponse
     * @param businessId
     */
    public void processResponseResults(JSONObject jsonObjectResponse, String businessId, String saveType, ProcessInstance processInstance){
        //设置返回单据类型
        String saveTypeResult;
        if (saveType.equals("fundCollection")){
            saveTypeResult = "收款单";
        }else {
            saveTypeResult = "付款单";
        }
        //处理响应结果
        if (jsonObjectResponse != null){
            logger.info("响应编码{}", jsonObjectResponse.getStr("code"));
            if (jsonObjectResponse.getStr("code").equals("200")){
                //保存成功，数据库中修改标记
                if (processInstance != null){
                    //根据审批实例id修改保存状态
                    System.out.println(processInstance);
                    processinstanceMapper.logicSaveById(processInstance);
                }
                logger.info("费用报销单据{}[{}]{}", businessId, saveTypeResult,jsonObjectResponse.getStr("message"));  //打印保存成功信息
            }else {
                //调用api报错回显
                //JSONArray responseJSONArray = jsonObjectResponse.getJSONArray("message");
                //api报错信息
//                StringBuilder errorMessage = new StringBuilder();
//                for (int i = 0; i< responseJSONArray.size();i++){
//                    errorMessage.append("[").append(responseJSONArray.getJSONObject(0).getStr("message")).append("]");
//                }
                //logger.error("{\"error\":\"调用{}api出错-费用报销审批单据{}中{}\"}", saveTypeResult,businessId, jsonObjectResponse.getStr("message"));
                String errorMessage = String.format("调用[%s]api出错-费用报销审批单据%s", saveTypeResult, businessId);
                Map<String,Object> jsonObjectResponseBean = jsonObjectResponse.toBean(Map.class);
                jsonObjectResponseBean.put("errorBusiness",errorMessage);
                throw new RuntimeException(JSONUtil.toJsonStr(jsonObjectResponseBean));
            }
        }
        logger.info("--------------------------------------------------------------------------------------------------------");
    }

    @Override
    public ProcessInstance getProcessInstance(JSONArray jsonArrayTasks) {
        ProcessInstance processInstance = new ProcessInstance();
        for (int i = 0; i < jsonArrayTasks.size(); i++) {
            JSONObject task = jsonArrayTasks.getJSONObject(i);
            if ("RUNNING".equals(task.getStr("status"))){
                String pcUrl = task.getStr("pcUrl");
                // 正则表达式匹配 procInsId 及其值
                String regex = "procInsId=([^&]+)";
                Pattern pattern = Pattern.compile(regex);
                Matcher matcher = pattern.matcher(pcUrl);
                if (matcher.find()) {
                    // 提取 procInsId 的值
                    processInstance.setProcessInstanceId(matcher.group(1));
                    //获取审批时间
                    String date = task.getStr("createTime");
                    ZonedDateTime zdt = ZonedDateTime.parse(date);
                    Date dateTime = Date.from(zdt.toInstant());
//                    processInstance.setCreateDate(task.getStr("createTime"));
                    processInstance.setCreateDate(dateTime);
                    System.out.println("ProcInsId: " + processInstance.getProcessInstanceId());
                } else {
                    System.out.println("procInsId not found in the URL.");
                }
                break;
            }
        }
        return processInstance;
    }


}
